# Python 常用高阶函数
from functools import reduce

# 高阶函数是指能够接收函数作为参数或者返回函数的函数。
# Python 内置了很多高阶函数，如 map()、reduce()、filter()、sorted() 等。
# map(),filter()适合处理大数据(逐项处理，不一次性加载到内存)


# map()
# map() 函数接收两个参数，一个是函数，一个是可迭代对象，map 将传入的函数依次作用到序列的每个元素，并把结果作为新的迭代器返回。
numbers = [1, 2, 3, 4, 5]
result = list(map(lambda x: x ** 2, numbers))
print(result)  # [1, 4, 9, 16, 25]


# reduce()
# reduce() 函数接收两个参数，一个是函数，一个是可迭代对象，reduce 把可迭代对象的元素迭代地应用到函数上，并返回最终的结果。
# 应用场景：求和、求积、求最大值、求最小值、字符串拼接、列表合并、字典合并等。
result = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(result)


# filter()
# filter() 函数接收两个参数，一个是函数，一个是可迭代对象，filter() 返回一个迭代器，
# 其中包含输入序列中所有使得函数返回 True 的元素。
result = list(filter(lambda x: x % 2 == 0, numbers))
print(result)


# sorted()
# sorted() 函数接收一个可迭代对象，并返回一个新的列表，其中包含排序后的可迭代对象。
# 排序是按照默认顺序进行的，如果要指定排序的规则，可以传入一个 key 函数。
words = ['apple', 'banana', 'orange', 'pear']
result = sorted(words, key=lambda x: len(x))
print(result)  # ['pear', 'apple', 'banana', 'orange']


# 练习：
# 编写一个函数，接收一个列表，返回一个新的列表，其中包含原列表中所有偶数的平方。
# 例如：
# input: [1, 2, 3, 4, 5]
# output: [4, 16]
def square_even(numbers):
    return list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers)))
print(square_even([1, 2, 3, 4, 5]))  # [4, 16]


# 过滤非整数
data = [5, 12, 8, "10", 3.14, "7"]
result = list(filter(lambda x: isinstance(x, int), data))
print(result)  # [5, 12, 8]


# 字典合并
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
d3 = {'d': 5}
result = {**d1, **d2, **d3}
print(result)  # {'a': 1, 'b': 3, 'c': 4, 'd': 5}


# 注意事项：
# 惰性求值与内存管理
# map, filter 返回的迭代器是惰性求值的，即只有在需要的时候才会计算值。
# 这意味着，如果 map, filter 后面没有对结果进行处理，则不会执行计算。
# 另外，map, filter 不会保存整个输入序列到内存中，而是使用生成器的方式，只在需要的时候计算值。
# 因此，如果输入序列很大，则需要对其进行切片处理，避免内存溢出。

# 可读性与简洁的平衡
# 高阶函数的使用可以让代码更加简洁、易读，但也要注意不要滥用。
# 过度使用高阶函数会导致代码难以理解和维护，因此需要在适当的场景下使用。
# 不推荐
squared_iter = map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, data))
# 推荐
filtered_data = (x for x in data if isinstance(x, int))
squared_result = (x * 2 for x in filtered_data)